package org.stwy.lease.rent;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.stwy.lease.contract.ContractEntity;

import com.rap.common.exception.ServiceException;
import com.rap.common.persistence.IBaseDAO;
import com.rap.common.service.BaseServiceImpl;
import com.rap.common.utils.DateUtil;

/**
 * 租金收缴 服务类
 */
/**
*版权信息 (c) RAP 保留所有权利.
*@author Rap.Codegen
*@Team RAP Team
*@Date 2015-4-25 12:31:24
*<p></p>
*
*@参与人：Rap.Codegen
*/
 
@Service
@Transactional(rollbackFor=Exception.class)
public class RentService extends BaseServiceImpl<RentEntity, String> {

	@Autowired
	private RentDAO dao;

	@Override
	protected IBaseDAO getDAO() {
		return dao;
	}
	/**
	 * 保存收租记录
	 */
	@Override
	public RentEntity save(RentEntity entity) throws ServiceException {
		entity = super.save(entity);
		//如果是已付款则生成下一次待缴纳的记录
		if(entity.getHasPay().intValue()==1){
			if(shouldAddNextRent(entity)){
				Date beginDate = DateUtils.addDays(entity.getEndDate(), 1);
				addNextToPayRecord(entity.getContract(),beginDate);
			}
		}
		return entity;
	}
	/**
	 * 判断是否需要缴纳下一条待收租记录。
	 * 如果当前收租记录的结束时间小于合同的结束时间则需要生成，否则不需要生成。
	 * @param rent
	 * @return
	 */
	public boolean shouldAddNextRent(RentEntity rent) {
		if(rent.getEndDate().before(rent.getContract().getEndDate())){
			return true;
		}
		return false;
	}
	/**
	 * 生成下一条待缴纳记录
	 * @param rent
	 * @throws ServiceException
	 */
	public void addNextToPayRecord(ContractEntity contract,Date beginDate) throws ServiceException {
		RentEntity nextRent = new RentEntity();
		nextRent.setContract(contract);
		nextRent.setBeginDate(beginDate);
		Date endDate = getEndDate(nextRent.getBeginDate(),contract.getPayType(),contract.getEndDate());
		nextRent.setEndDate(endDate);
		nextRent.setHasPay(0);
		nextRent.setIsInit(false);
		nextRent.setMoney(null);
		nextRent.setPayDate(null);
		Date shoulPayDate = getShouldPayDate(nextRent.getBeginDate(),contract.getBeforeDay());
		nextRent.setShouldPayDate(shoulPayDate);
		Double shouldPayMoney = getShouldPayMoney(contract.getPrice()
				,nextRent.getBeginDate()
				,contract.getAdjustDate()
				,contract.getIncrease()
				,contract.getIncreaseType()
				,contract.getIncreaseHandle()
				,contract.getRent()
				,contract.getArea());
		nextRent.setShouldPayMoney(shouldPayMoney);
		nextRent.setStatus(1);
		RentEntity preRent = this.getlastHasPayRecordByContractId(contract.getUuid());
		if(preRent!=null){
			nextRent.setLeave(preRent.getLeave());
		}
		super.save(nextRent);
	}
	/**
	 * 获取租金期至
	 * @param beginDate
	 * @param payType
	 * @return
	 */
	private Date getEndDate(Date beginDate, String payType,Date contractEndDate) throws ServiceException{
		Date endDate=null;
		if(ContractEntity.CONTRACT_PAY_TYPE_MONTH.equals(payType)){
			int year = DateUtil.getYear(beginDate);
	        int month = DateUtil.getMonth(beginDate);
	        int day = DateUtil.getDay(beginDate);
	        if(day>=28){
    			int lastDay = DateUtil.getDay(DateUtil.getLastDayOfMonth(year, month+1));
    			if(lastDay>=(day-1)){//如果下个月存在这一天（）,则以这一天为结束日，否则以下个月最后一天为结束日
    				endDate = DateUtil.getDate(year, month+1, day-1);
    			}else{
    				endDate = DateUtil.getDate(year, month+1, lastDay);
    			}
	        }else{
	        	endDate = DateUtils.addDays(DateUtil.getDate(DateUtil.getYear(beginDate), month+1, day), -1);
	        }
			
		}else if(ContractEntity.CONTRACT_PAY_TYPE_QUATER.equals(payType)){
			int season = DateUtil.getSeason(beginDate);
			if(season==1){
				endDate = DateUtil.getDate(DateUtil.getYear(beginDate), 3, 31);
			}else if(season==2){
				endDate = DateUtil.getDate(DateUtil.getYear(beginDate), 6, 30);
			}else if(season==3){
				endDate = DateUtil.getDate(DateUtil.getYear(beginDate), 9, 30);
			}else if(season==4){
				endDate = DateUtil.getDate(DateUtil.getYear(beginDate), 12, 31);
			}else{
				throw new ServiceException("出现异常，季度获取有错误");
			}
		}else if(ContractEntity.CONTRACT_PAY_TYPE_HALFYEAR.equals(payType)){
			//开始时间小于6月份就是上半年，开始时间大于等于6月份就是下半年
			Date midDate = DateUtil.getDate(DateUtil.getYear(beginDate), 6, 1);
			if(beginDate.before(midDate)){
				endDate = DateUtil.getDate(DateUtil.getYear(beginDate), 5, 31);
			}else{
				endDate = DateUtil.getDate(DateUtil.getYear(beginDate), 12, 31);
			}
		}else if(ContractEntity.CONTRACT_PAY_TYPE_YEAR.equals(payType)){
			endDate = DateUtil.getDate(DateUtil.getYear(beginDate), 12, 31);
		}else if(ContractEntity.CONTRACT_PAY_TYPE_ONETIME.equals(payType)){
			endDate = contractEndDate;
		}else{
			throw new ServiceException("出现异常，支付类型为空");
		}
		
		//如果计算出来的租金日期大于合同结束日期，则以合同结束日期为准
		if(endDate.after(contractEndDate)){
			endDate = contractEndDate;
		}
		return endDate;
	}
	/**
	 * 获取应该交租的日期
	 * @param beginDate 租期开始日期
	 * @param beforeDay 提前交租天数
	 * @return
	 */
	private Date getShouldPayDate(Date beginDate, Integer beforeDay) {
		if(beforeDay==null){
			return beginDate;
		}
		return DateUtils.addDays(beginDate, (0-beforeDay));
	}
	/**
	 * 获取应该支付的租金
	 * @param price
	 * @param beginDate 开始日期
	 * @param adjustDate 调租日期
	 * @param increase 增幅 数字
	 * @param increaseType 增幅类型： 元，百分比
	 * @param increaseHandle 增幅方式：整体，每平方
	 * @param rent 租金
	 * @param area 承租总面积
	 * @return
	 */
	private Double getShouldPayMoney(Double price, Date beginDate,
			Date adjustDate, Double increase,String increaseType, String increaseHandle, Double rent,Double area) {
		try{
			if(adjustDate==null){
				return rent;
			}else{
				if(!adjustDate.after(beginDate)){
					int adjustTimes = getAdjustTimes(adjustDate,beginDate);//调价次数
					Double returnRent = rent;
					for(int i=0;i<adjustTimes;i++){
						returnRent=getMoneyAfterIncrease(price,increase,increaseType,increaseHandle,returnRent,area);
					}
					return returnRent;
				}else{
					return rent;
				}
			}
		}catch(Exception e){
			e.printStackTrace();
			return rent;
		}
	}
	/**
	 * 根据初次调价日期和收租日期获取调价次数
	 * @param adjustDate
	 * @param rentDate
	 * @return
	 */
	private int getAdjustTimes(Date adjustDate, Date rentDate) {
		int times=0;
		if(!adjustDate.after(rentDate)){
			times = DateUtil.getYear(rentDate)-DateUtil.getYear(adjustDate);
			if(DateUtil.getMonth(rentDate)>DateUtil.getMonth(adjustDate)){
				times++;
			}else if(DateUtil.getMonth(rentDate)==DateUtil.getMonth(adjustDate)){
				if(DateUtil.getDay(rentDate)>=DateUtil.getDay(adjustDate)){
					times++;
				}
			}
		}
		return times;
	}
	/**
	 * 获取增幅后的租金
	 * @param price
	 * @param increase
	 * @param increaseType
	 * @param rent 
	 * @param increaseHandle 
	 * @return
	 */
	private Double getMoneyAfterIncrease(Double price, Double increase,
			String increaseType, String increaseHandle, Double rent,Double area) {
		if(increase==null||increase.doubleValue()==0){
			return rent;
		}else{
			if(ContractEntity.CONTRACT_INCREASE_HANDLE_EVERY.equals(increaseHandle)){
				if(ContractEntity.CONTRACT_INCREASE_TYPE_PERCENT.equals(increaseType)){
					return rent+((price*(increase/100))*area);
				}else{
					return rent+(increase*area);
				}
			}else{
				//整体，默认（整体）
				if(ContractEntity.CONTRACT_INCREASE_TYPE_PERCENT.equals(increaseType)){
					return rent+rent*(increase/100);
				}else{
					return rent+increase;
				}
			}
		}
	}
	/**
	 * 获取某天待交租的记录
	 * @param curDate
	 * @return
	 * @throws ServiceException
	 */
	public List<RentEntity> findToPayRecords(Date curDate) throws ServiceException {
		return dao.findToPayRecords(curDate);
	}
	/**
	 * 保存租金收缴记录
	 * @param uuids
	 * @param payDates
	 * @param moneys
	 * @param historys
	 * @param depositNows
	 * @param remarks 
	 * @throws ServiceException
	 */
	public void saveRents(String[] uuids, String[] payDates, String[] moneys,String[] leaves
			, String[] depositNows,String[] endDates, String[] repayMoneys, String[] prepayMoneys, String[] remarks) throws ServiceException{
		int i=0;
		for(String uuid:uuids){
			RentEntity rent = get(uuid);
			rent.setPayDate(DateUtil.strToDate(payDates[i]));
			rent.setMoney(Double.parseDouble(moneys[i]));
			rent.setLeave(Double.parseDouble(leaves[i]));
			rent.setDepositNow(Double.parseDouble(depositNows[i]));
			rent.setEndDate(DateUtil.strToDate(endDates[i]));
			rent.setRepayMoney(Double.parseDouble(repayMoneys[i]));
			rent.setPrepayMoney(Double.parseDouble(prepayMoneys[i]));
			try{
				rent.setRemark(remarks[i]);
			}catch(Exception e){
			}
			rent.setHasPay(1);
			this.save(rent);
			i++;
		}
	}
	/**
	 * 根据合同id获取最后一条记录
	 * @param contractId 合同Id
	 * @return
	 * @throws ServiceException
	 */
	public RentEntity getlastRecordByContractId(String contractId) throws ServiceException {
		return dao.getlastRecordByContractId(contractId);
	}
	/**
	 * 根据合同id获取最后一条记录
	 * @param contractId 合同Id
	 * @return
	 * @throws ServiceException
	 */
	public RentEntity getlastToPayRecordByContractId(String contractId) throws ServiceException {
		return dao.getlastToPayRecordByContractId(contractId);
	}
	/**
	 * 根据合同id获取最后一条记录
	 * @param contractId 合同Id
	 * @return
	 * @throws ServiceException
	 */
	public RentEntity getlastHasPayRecordByContractId(String contractId) throws ServiceException {
		return dao.getlastHasPayRecordByContractId(contractId);
	}
}
